package souralven.jcomicreader.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import souralven.jcomicreader.model.FileFormat;

/**
 * Utility methods to deal with comic files.
 */
public final class FileUtil {
	/**
	 * Magic bytes to identify a PDF archive.
	 */
	private static final String MAGIC_PDF = "%PDF";
	private static final int MAGIC_PDF_LENGTH = MAGIC_PDF.length();
	/**
	 * Magic bytes to identify a RAR archive.
	 */
	private static final String MAGIC_RAR = "Rar!";
	private static final int MAGIC_RAR_LENGTH = MAGIC_RAR.length();
	/**
	 * Magic bytes to identify a ZIP archive.
	 */
	private static final String MAGIC_ZIP = "PK";
	private static final int MAGIC_ZIP_LENGTH = MAGIC_ZIP.length();

	private static final int MAGIC_MAX_LENGTH = Math.max(MAGIC_PDF_LENGTH, Math
			.max(MAGIC_RAR_LENGTH, MAGIC_ZIP_LENGTH));

	private FileUtil() {
	}


	/**
	 * Figure out file type by looking at magic bytes.
	 * 
	 * @throws IOException
	 *             in case the format cannot be determined
	 */
	public static FileFormat obtainComicFormat(final File comicFile)
			throws IOException {
		assert comicFile != null;
		InputStream in = new FileInputStream(comicFile);
		FileFormat result = null;

		try {
			byte[] magicBytes = new byte[MAGIC_MAX_LENGTH];
			String fullMagicText;

			in.read(magicBytes, 0, MAGIC_MAX_LENGTH);
			fullMagicText = new String(magicBytes, "US-ASCII");

			int fullMagicTextLength = fullMagicText.length();

			if (fullMagicTextLength >= MAGIC_RAR_LENGTH) {
				String magicText = fullMagicText.substring(0, MAGIC_RAR_LENGTH);

				// TODO: Find out if magic bytes are exactly "Rar!", and use
				// equals().
				if (magicText.equalsIgnoreCase(MAGIC_RAR)) {
					result = FileFormat.RAR;
				}
			}
			if ((result == null) && (fullMagicTextLength >= MAGIC_ZIP_LENGTH)) {
				String magicText = fullMagicText.substring(0, MAGIC_ZIP_LENGTH);

				if (magicText.equals(MAGIC_ZIP)) {
					result = FileFormat.ZIP;
				}
			}
			if ((result == null) && (fullMagicTextLength >= MAGIC_PDF_LENGTH)) {
				String magicText = fullMagicText.substring(0, MAGIC_PDF_LENGTH);

				if (magicText.equals(MAGIC_PDF)) {
					result = FileFormat.PDF;
				}
			}
			if (result == null) {
				Object[] options = new Object[] { comicFile, fullMagicText };
				String errorMessage = MessageUtil.getMessage(
						"errors.cannotDetermineComicFileType", options);

				throw new IOException(errorMessage);
			}
		} finally {
			in.close();
		}
		return result;
	}
}
